From e8e8d15e36f783fc836ee14be5cf5746a777b837 Mon Sep 17 00:00:00 2001 From: Jimi Xenidis Date: Thu, 21 Sep 2006 07:36:17 -0400 Subject: [PATCH] [XEN][POWERPC] SCOM access is fully known and working Signed-off-by: Jimi Xenidis Signed-off-by: Hollis Blanchard --HG-- extra : transplant_source : %E2%2C%BD.%A1%E4r%0BxS%E4%B0ZJ%9C%DD%A2%BF%F3H --- xen/arch/powerpc/powerpc64/ppc970_scom.c | 161 +++++++++++++++-------- 1 file changed, 109 insertions(+), 52 deletions(-) diff --git a/xen/arch/powerpc/powerpc64/ppc970_scom.c b/xen/arch/powerpc/powerpc64/ppc970_scom.c index 17486363fb..2da6534886 100644 --- a/xen/arch/powerpc/powerpc64/ppc970_scom.c +++ b/xen/arch/powerpc/powerpc64/ppc970_scom.c @@ -22,33 +22,13 @@ #include #include #include +#include +#include #define SPRN_SCOMC 276 #define SPRN_SCOMD 277 - -static inline void mtscomc(ulong scomc) -{ - __asm__ __volatile__ ("mtspr %1, %0" : : "r" (scomc), "i"(SPRN_SCOMC)); -} - -static inline ulong mfscomc(void) -{ - ulong scomc; - __asm__ __volatile__ ("mfspr %0, %1" : "=r" (scomc): "i"(SPRN_SCOMC)); - return scomc; -} - -static inline void mtscomd(ulong scomd) -{ - __asm__ __volatile__ ("mtspr %1, %0" : : "r" (scomd), "i"(SPRN_SCOMD)); -} - -static inline ulong mfscomd(void) -{ - ulong scomd; - __asm__ __volatile__ ("mfspr %0, %1" : "=r" (scomd): "i"(SPRN_SCOMD)); - return scomd; -} +#define SCOMC_READ 1 +#define SCOMC_WRITE (!(SCOMC_READ)) union scomc { struct scomc_bits { @@ -68,50 +48,127 @@ union scomc { }; -static inline ulong read_scom(ulong addr) +static inline int read_scom(uint addr, ulong *d) { union scomc c; - ulong d; - - c.word = 0; - c.bits.addr = addr; - c.bits.RW = 0; - - mtscomc(c.word); - d = mfscomd(); - c.word = mfscomc(); - if (c.bits.failure) - panic("scom status: 0x%016lx\n", c.word); - - return d; + ulong flags; + + /* drop the low 8bits (including parity) */ + addr >>= 8; + + /* these give iface errors because the address is ambiguous after + * the above bit dropping */ + BUG_ON(addr == 0x8000); + + for (;;) { + c.word = 0; + c.bits.addr = addr; + c.bits.RW = SCOMC_READ; + + local_irq_save(flags); + asm volatile ( + "sync \n\t" + "mtspr %2, %0 \n\t" + "isync \n\t" + "mfspr %1, %3 \n\t" + "isync \n\t" + "mfspr %0, %2 \n\t" + "isync \n\t" + : "+r" (c.word), "=r" (*d) + : "i"(SPRN_SCOMC), "i"(SPRN_SCOMD)); + + local_irq_restore(flags); + /* WARNING! older 970s (pre FX) shift the bits right 1 position */ + + if (!c.bits.failure) + return 0; + + /* deal with errors */ + /* has SCOM been disabled? */ + if (c.bits.disabled) + return -ENOSYS; + + /* we were passed a bad addr return -1 */ + if (c.bits.addr_error) + return -EINVAL; + + /* this is way bad and we will checkstop soon */ + BUG_ON(c.bits.proto_error); + + if (c.bits.iface_error) + udelay(10); + } } -static inline void write_scom(ulong addr, ulong val) +static inline int write_scom(uint addr, ulong d) { union scomc c; - - c.word = 0; - c.bits.addr = addr; - c.bits.RW = 1; - - mtscomd(val); - mtscomc(c.word); - c.word = mfscomc(); - if (c.bits.failure) - panic("scom status: 0x%016lx\n", c.word); + ulong flags; + + /* drop the low 8bits (including parity) */ + addr >>= 8; + + /* these give iface errors because the address is ambiguous after + * the above bit dropping */ + BUG_ON(addr == 0x8000); + + for (;;) { + c.word = 0; + c.bits.addr = addr; + c.bits.RW = SCOMC_WRITE; + + local_irq_save(flags); + asm volatile( + "sync \n\t" + "mtspr %3, %1 \n\t" + "isync \n\t" + "mtspr %2, %0 \n\t" + "isync \n\t" + "mfspr %0, %2 \n\t" + "isync \n\t" + : "+r" (c.word) + : "r" (d), "i"(SPRN_SCOMC), "i"(SPRN_SCOMD)); + local_irq_restore(flags); + + if (!c.bits.failure) + return 0; + + /* has SCOM been disabled? */ + if (c.bits.disabled) + return -ENOSYS; + + /* we were passed a bad addr return -1 */ + if (c.bits.addr_error) + return -EINVAL; + + /* this is way bad and we will checkstop soon */ + BUG_ON(c.bits.proto_error); + + /* check for iface and retry */ + if (c.bits.iface_error) + udelay(10); + } } +/* SCOMC addresses are 16bit but we are given 24 bits in the + * books. The low oerder 8 bits are some kinda parity thin and should + * be ignored */ #define SCOM_AMCS_REG 0x022601 #define SCOM_AMCS_AND_MASK 0x022700 #define SCOM_AMCS_OR_MASK 0x022800 #define SCOM_CMCE 0x030901 #define SCOM_PMCR 0x400801 +#define SCOM_PTSR 0x408001 + +/* cannot access these since only top 16bits are considered */ +#define SCOM_STATUS 0x800003 void cpu_scom_init(void) { -#ifdef not_yet + ulong val; console_start_sync(); - printk("scom PMCR: 0x%016lx\n", read_scom(SCOM_PMCR)); + if (!read_scom(SCOM_PTSR, &val)) + printk("SCOM PTSR: 0x%016lx\n", val); + console_end_sync(); -#endif } -- 2.30.2